// 动画层 线 相关部分
import { transform, getTransform } from 'ol/proj' // 坐标转换
import Feature from 'ol/Feature'
import Point from 'ol/geom/Point'
import LineString from 'ol/geom/LineString'
import Polygon from 'ol/geom/Polygon'
import Circle from 'ol/geom/Circle'

import {
  Circle as CircleStyle,
  Fill,
  Stroke,
  Style,
  Text
} from 'ol/style'
import Icon from 'ol/style/Icon'
import Overlay from 'ol/Overlay'

export default {
  data () {
    return {
      // oMap: null, // 地图对象;    简写对照 overlay[ovl], arrow[arw], sprite[spt], Endpoint[ept]
      sSRS: 'EPSG:4326', // 空间参照系（Spatial Reference System); 表示使用的数据的坐标系，和地图用的RCS不是同一个
      // sMapRCS 此变量在animLayer.vue文件中
      // FeatureLayer: null, // POI层，所有操作在此组件中完成，故放此处
      // aStyleList: null, // 父类定义的样式列表，POI需要使用，所以初始化时引入！
      // sIconType: 'standard' // 引入mapStyle.js会混入此变量，cardMap也会引入此变量；两者又相同。
      // animSelected: null // 动画层中选中的对象 {id：当前选中的featureID，style: 选中feature原来的样式} 在动画层中定义
      sMarkColor: '#F00' // 标记选中对象的颜色--选中为红色
    }
  },
  watch: {
    // watch
  },
  mounted () {
    // mounted
  },
  methods: {
    // 动画的样式设置都在animLayer中
    // getAnimStyle(sStyleID) {}

    /**
     * @description 绘制线的端点
     * @param {string} gID 组ID-- 关联路径的ID
     * @param {array} aCoord 获取的资源数据
     * @param {string} sText 显示端点的文字
     * @param {string} sIcon 点使用的图片
     * @param {string} sColor 颜色(端点和文字)
     * @param {int} size 尺寸(点的大小) -- 在数据文件中指定
     */
    drawEndpoint (gID, aCoord, sText = null, sIcon = null, sColor = '#00f', iSize = 8) {
      sColor = sColor || '#00f'
      iSize = iSize || 8
      const geoPoint = new Point(aCoord)
      const endPoint = new Feature({
        geometry: geoPoint,
        dType: 'epoint',
        dClass: gID
      })
      // const iSrc = '/mapres/images/icon/' + this.sIconType + '/' + sIcon + '.png'
      // 端点样式设置
      const oStyle = new Style()
      if (sText) {
        const oText = new Text({ // ol.style.Text
          font: '12px sans-serif', // iFont字体与大小
          // offsetX: 0 文字偏移
          offsetY: iSize * 2,
          text: sText,
          fill: new Fill({ // 文字填充色
            color: sColor // iFill
          }),
          stroke: new Stroke({ // 文字边界宽度
            color: '#fff', // iStrokeColor,
            width: 3 // iStrokeWidth
          })
        })
        oStyle.setText(oText)
      }
      if (sIcon) { // 如果有icon，使用sIcon指定的图片名称；不使用Circle作为点图标
        const iSrc = '/mapres/images/icon/' + this.sIconType + '/' + sIcon + '.png'
        const oIcon = new Icon({
          crossOrigin: 'anonymous', // 文档中要求必须添加？待验证
          src: iSrc
        })
        oStyle.setImage(oIcon)
      } else {
        const oCircleStyle = new CircleStyle({
          radius: iSize, // cRadius,
          fill: new Fill({ // 圆形
            color: sColor // cFill
          }),
          stroke: new Stroke({ // 文字边界宽度
            color: '#fff', // iStrokeColor,
            width: 3 // iStrokeWidth
          })
        })
        oStyle.setImage(oCircleStyle)
      }
      endPoint.setStyle(oStyle)
      this.animSource.addFeature(endPoint)
    },

    /**
     * @description 绘制圆方法()
     * @param {String} gID 位置值-和关系线相同
     * @param {Array} aCenter 圆心 (没有经过坐标转换的原始数据 4326)
     * @param {int} iRadius 半径，单位（米）
     * @param {String} sRCS 表示地图使用的坐标系,如：EPSG:3857
     * @param {Object} oStyle 绘制圆的样式
     * @param {String} sPrefix 前缀-用来与gid组合(如：'rcf_' Relation circle from; 'rct_' ~ To
     */
    drawCircleZone (gID, aCenter, iRadius, oStyle, sPrefix, sRCS = this.sMapRCS) {
      let cp = null
      if (this.sSRS !== 'EPSG:3857') {
        cp = transform(aCenter, this.sSRS, 'EPSG:3857')
      } else {
        cp = aCenter // 圆的中心点,3857坐标 不用转换
      }
      const geomCircle = new Circle(cp, iRadius)
      if (sRCS !== 'EPSG:3857') {
        geomCircle.applyTransform(getTransform('EPSG:3857', sRCS))
      }
      const CircleFeature = new Feature({ // ol.Feature
        geometry: geomCircle, // ol.geom.lineSting
        type: 'RZONE', // add for select
        dType: 'rzone', // Relation circle zone
        dClass: gID // 数据分类标志，选择时--通过此字段关联相同类的数据
      })
      CircleFeature.setId(sPrefix + gID) // 'rcf_' Relation circle from
      CircleFeature.setStyle(oStyle)
      this.animSource.addFeature(CircleFeature) // 绘制路线
    },
    /**
     * @description 显示路线的基本信息（疏散人数等）
     * @param {object} oLineFeature 线的基本信息
     */
    showLineBaseInfo (oLineFeature) {
      const geometry = oLineFeature.getGeometry()
      const iType = geometry.getType().toLowerCase() // 几何类型
      console.log(iType)
      if (iType !== 'linestring') return
      const alineCP = geometry.getCoordinateAt(0.5) // 获取路径的中心坐标（featrue从当前显示获取，不用坐标转换）
      // const alineCP = geometry.getLastCoordinate()
      // console.log(alineCP)
      // 获取气泡中的信息
      const sRoadInfo = oLineFeature.get('Bubble')
      let sBaseInfo = null
      if (sRoadInfo) { // 如果有气泡信息，获取基本信息
        sBaseInfo = sRoadInfo.summary // 获取概览信息
      }
      console.log(oLineFeature, sRoadInfo, sBaseInfo)
      if (sBaseInfo) { // 如果有概信息，展示到路径中心位置
        const sID = oLineFeature.getId()
        // 创建overlay
        const roadInfoDIV = document.createElement('div')
        roadInfoDIV.className = 'anim-baseinfo'
        roadInfoDIV.id = sID
        roadInfoDIV.innerHTML = sBaseInfo
        // 将气泡div添加到HTML--动画层
        const animContainer = document.getElementById('animate-container')
        animContainer.appendChild(roadInfoDIV)
        // 创建信息框
        const overlay = new Overlay({
          id: 'ovl_' + sID,
          element: roadInfoDIV,
          positioning: 'center-center',
          stopEvent: false,
          autoPan: true,
          autoPanAnimation: {
            duration: 250
          }
        })
        overlay.setPosition(alineCP)
        this.oMap.addOverlay(overlay)
        // 添加到地图上展示
      }
    },

    /**
     * @description 绘制路径线路
     * @param {Object} oSource 获取的资源数据
     * @param {String} sRCS 表示地图使用的坐标系,如：EPSG:3857
     */
    drawRoadLine (oSource, sRCS = this.sMapRCS) {
      const oBubble = oSource.properties.Bubble || null
      const dClass = oSource.properties.dClass || oSource.properties.dType // 默认值从null改成id // 保留字段(相同值属于一组，选择时确认)
      const sExt = oSource.properties.ext || 'ROAD' // 创建Feature的类型
      const hasArrow = oSource.properties.hasArrow || null // 是否存在箭头
      const hasEndPoint = oSource.properties.hasEndpoint || null // 是否绘制端点
      const lineCoord = oSource.geometry.coordinates // 获得线的顶点信息
      const geometry = new LineString(lineCoord)
      if (sRCS !== this.sSRS) {
        // geometry.applyTransform(getTransform('EPSG:4326', sViewProj))
        geometry.applyTransform(getTransform(this.sSRS, sRCS))
      }
      // 创建lineSting Feature
      const lineFeature = new Feature({ // ol.Feature
        geometry: geometry, // ol.geom.lineSting
        type: sExt, // add for select
        dType: oSource.properties.dType, // 类型,如:default 代表直线，curve 代表曲线 等
        dClass: dClass, // 数据分类标志，选择时--通过此字段关联相同类的数据（同时选择路线和其上车辆）
        Bubble: oBubble
      })
      lineFeature.setId(oSource.properties.id)
      // console.log(this.getPOIStyle (oSource.properties))
      lineFeature.setStyle(this.getAnimStyle(oSource.properties))
      // this.FeatureLayer.getSource().addFeature(poiFeature)
      // this.animSource.addFeature(lineFeature) -- 要先绘制端点
      // 绘制端点
      if (hasEndPoint) {
        let sFromName = null
        let sFromIcon = null
        let sFromColor = null
        let iFromSize = null
        let sToName = null
        let sToIcon = null
        let sToColor = null
        let iToSize = null
        if (oSource.from) {
          sFromName = oSource.from.name || null
          sFromIcon = oSource.from.icon || null
          sFromColor = oSource.from.color || null
          iFromSize = oSource.from.size || null
        }

        if (oSource.to) {
          sToName = oSource.to.name || null
          sToIcon = oSource.to.icon || null
          sToColor = oSource.to.color || null
          iToSize = oSource.to.size || null
        }
        // (aCoord, sText, sIcon, sColor, iSize)
        // console.log(sFromName, sFromIcon, sFromColor, iFromSize)
        this.drawEndpoint(dClass, geometry.getFirstCoordinate(), sFromName, sFromIcon, sFromColor, iFromSize)
        this.drawEndpoint(dClass, geometry.getLastCoordinate(), sToName, sToIcon, sToColor, iToSize)
      }
      this.animSource.addFeature(lineFeature) // 绘制路线
      // 如果有箭头需要添加箭头
      if (hasArrow) {
        const strokeColor = lineFeature.getStyle().getStroke().getColor()
        const aGeometry = geometry.getCoordinates()
        const n = aGeometry.length
        const dx = aGeometry[n - 1][0] - aGeometry[n - 2][0] // end[0] - start[0];
        const dy = aGeometry[n - 1][1] - aGeometry[n - 2][1] // end[1] - start[1];
        const rotation = Math.atan2(dy, dx)
        const geoPoint = new Point(geometry.getLastCoordinate())
        const lineArrow = new Feature({
          geometry: geoPoint,
          dType: 'arrow',
          dClass: dClass
        })
        lineArrow.setId('arw_' + oSource.properties.id)
        const arrowStyle = new Style({
          image: new Icon({
            color: strokeColor,
            crossOrigin: 'anonymous',
            src: '/mapres/images/icon/arrow_0.png',
            anchor: [0.75, 0.5],
            // rotateWithView: true,
            rotation: -rotation
          })
        })
        lineArrow.setStyle(arrowStyle)
        this.animSource.addFeature(lineArrow)
      }
      // 显示路径基本信息
      this.showLineBaseInfo(lineFeature)
    },

    /**
     * @description 绘制曲线路径(由起点和终点)
     * @param {Object} oSource 获取的资源数据
     * @param {String} sRCS 表示地图使用的坐标系,如：EPSG:3857
     */
    drawCurveOfTwoPoint (oSource, sRCS = this.sMapRCS) {
      // 获取属性信息
      const oBubble = oSource.properties.Bubble || null
      const dClass = oSource.properties.dClass || oSource.properties.dType // 默认值从null改成id // 保留字段(相同值属于一组，选择时确认)
      const sExt = oSource.properties.ext || 'ROAD' // 创建Feature的类型
      const hasArrow = oSource.properties.hasArrow || null // 是否存在箭头
      const hasEndPoint = oSource.properties.hasEndpoint || null // 是否绘制端点
      // 获得线的顶点信息(from to)
      const p1 = oSource.from.coordinates
      const p2 = oSource.to.coordinates
      const iLen = this.CalLengthOfTwoPoints(p1, p2)
      const h = iLen / 2 // 获取三角形高度 - height
      const cp = this.getCtrlPointOfTwoPoints(p1, p2, h)
      const aBezierPoints = this.getBezierPoints([p1, cp, p2]) // 根据点数据生成曲线点
      // console.dir(aBezierPoints)
      const geometry = new LineString(aBezierPoints)
      if (sRCS !== this.sSRS) {
        // 进行坐标转换
        geometry.applyTransform(getTransform(this.sSRS, sRCS))
      }
      // 创建lineSting Feature
      const lineFeature = new Feature({ // ol.Feature
        geometry: geometry, // ol.geom.lineSting
        type: sExt, // add for select
        dType: oSource.properties.dType, // 类型,如:default 代表直线，curve 代表曲线 等
        dClass: dClass, // 数据分类标志，选择时--通过此字段关联相同类的数据（同时选择路线和其上车辆）
        Bubble: oBubble
      })
      lineFeature.setId(oSource.properties.id)
      // console.log(this.getPOIStyle (oSource.properties))
      lineFeature.setStyle(this.getAnimStyle(oSource.properties))
      // 绘制端点
      if (hasEndPoint) {
        let sFromName = null
        let sFromIcon = null
        let sFromColor = null
        let iFromSize = null
        let sToName = null
        let sToIcon = null
        let sToColor = null
        let iToSize = null
        if (oSource.from) {
          sFromName = oSource.from.name || null
          sFromIcon = oSource.from.icon || null
          sFromColor = oSource.from.color || null
          iFromSize = oSource.from.size || null
        }

        if (oSource.to) {
          sToName = oSource.to.name || null
          sToIcon = oSource.to.icon || null
          sToColor = oSource.to.color || null
          iToSize = oSource.to.size || null
        }
        // (aCoord, sText, sIcon, sColor, iSize)
        // console.log(sFromName, sFromIcon, sFromColor, iFromSize)
        this.drawEndpoint(dClass, geometry.getFirstCoordinate(), sFromName, sFromIcon, sFromColor, iFromSize)
        this.drawEndpoint(dClass, geometry.getLastCoordinate(), sToName, sToIcon, sToColor, iToSize)
      }
      this.animSource.addFeature(lineFeature) // 绘制路线
      // 如果有箭头需要添加箭头
      if (hasArrow) {
        const strokeColor = lineFeature.getStyle().getStroke().getColor()
        const aGeometry = geometry.getCoordinates()
        const n = aGeometry.length
        const dx = aGeometry[n - 1][0] - aGeometry[n - 2][0] // end[0] - start[0];
        const dy = aGeometry[n - 1][1] - aGeometry[n - 2][1] // end[1] - start[1];
        const rotation = Math.atan2(dy, dx)
        const geoPoint = new Point(geometry.getLastCoordinate())
        const lineArrow = new Feature({
          geometry: geoPoint,
          dType: 'arrow',
          dClass: dClass
        })
        lineArrow.setId('arw_' + oSource.properties.id)
        const arrowStyle = new Style({
          image: new Icon({
            color: strokeColor,
            crossOrigin: 'anonymous',
            src: '/mapres/images/icon/arrow_0.png',
            anchor: [0.75, 0.5],
            // rotateWithView: true,
            rotation: -rotation
          })
        })
        lineArrow.setStyle(arrowStyle)
        this.animSource.addFeature(lineArrow)
      }
      // 显示路径基本信息
      this.showLineBaseInfo(lineFeature)
    },

    /**
     * @description 绘制关联线(关系图谱用)
     * @param {Object} oSource 获取的资源数据
     * @param {String} sRCS 表示地图使用的坐标系,如：EPSG:3857
     */
    drawRelationLine (oSource, sRCS = this.sMapRCS) {
      console.log(oSource)
      // 获取属性信息
      const oBubble = oSource.properties.Bubble || null
      const dClass = oSource.properties.dClass || oSource.properties.dType // 默认值从null改成id // 保留字段(相同值属于一组，选择时确认)
      const sExt = oSource.properties.ext || 'ROAD' // 创建Feature的类型
      const iDefRadius = 200 // 默认半径（单位米）

      // 获得线的顶点信息(from to)
      const p1 = oSource.from.coordinates
      const r1 = oSource.from.radius || iDefRadius
      const p2 = oSource.to.coordinates
      const r2 = oSource.to.radius || iDefRadius
      console.log(p1, p2, r1, r2)
      let cp1 = null
      let cp2 = null
      if (this.sSRS !== 'EPSG:3857') {
        cp1 = transform(p1, this.sSRS, 'EPSG:3857')
        cp2 = transform(p2, this.sSRS, 'EPSG:3857')
      } else {
        cp1 = p1 // 第一个圆的中心点,3857坐标
        cp2 = p2 // 第二个圆的中心点
      }
      // 绘制两个圆 -- Circle(center, opt_radius, opt_layout)
      // const geomC1 = new Circle(cp1, r1)
      // if (sRCS !== 'EPSG:3857') {
      //   geomC1.applyTransform(getTransform('EPSG:3857', sRCS))
      // }
      // const FromCircle = new Feature({ // ol.Feature
      //   geometry: geomC1, // ol.geom.lineSting
      //   type: sExt, // add for select
      //   dType: 'rcz_', // Relation circle zone
      //   dClass: dClass, // 数据分类标志，选择时--通过此字段关联相同类的数据（同时选择路线和其上车辆）
      //   Bubble: oBubble
      // })
      // FromCircle.setId('rcf_' + oSource.properties.id) // Relation circle from
      // FromCircle.setStyle(this.getAnimStyle(oSource.properties))
      // this.animSource.addFeature(FromCircle) // 绘制路线
      // 计算两个点的长度(圆和线交点可以提出为一个方法)
      const L = this.CalLengthOfTwoPoints(cp1, cp2)
      // x3=x1+r/L(x2-x1)
      const x3 = cp1[0] + r1 / L * (cp2[0] - cp1[0])
      // y3=y1+r/L(y2-y1)
      const y3 = cp1[1] + r1 / L * (cp2[1] - cp1[1])
      // 求圆线交点2
      const x4 = cp2[0] + r2 / L * (cp1[0] - cp2[0])
      const y4 = cp2[1] + r2 / L * (cp1[1] - cp2[1])
      // 线坐标点（3857）
      const aLinePoints = this.getBezierPoints([[x3, y3], [x4, y4]])
      const geometry = new LineString(aLinePoints)
      if (sRCS !== 'EPSG:3857') {
        geometry.applyTransform(getTransform('EPSG:3857', sRCS))
      }
      // 创建lineSting Feature
      const lineFeature = new Feature({ // ol.Feature
        geometry: geometry, // ol.geom.lineSting
        type: sExt, // add for select
        dType: oSource.properties.dType, // 类型,如:default 代表直线，curve 代表曲线 等
        dClass: dClass, // 数据分类标志，选择时--通过此字段关联相同类的数据（同时选择路线和其上车辆）
        Bubble: oBubble
      })
      lineFeature.setId(oSource.properties.id)
      // console.log(this.getPOIStyle (oSource.properties))
      const oStyle = this.getAnimStyle(oSource.properties)
      lineFeature.setStyle(oStyle)
      // lineFeature.setStyle(this.getAnimStyle(oSource.properties))
      this.animSource.addFeature(lineFeature) // 绘制路线
      // 绘制圆
      // 如果后续选要填充圆--clone oStyle，修改样式填充色如rgba
      this.drawCircleZone(oSource.properties.id, p1, r1, oStyle, 'rcf_')
      this.drawCircleZone(oSource.properties.id, p2, r2, oStyle, 'rct_')
    },

    /**
     * @description 根据featrue的ID选择对象;所选可以是动画层中的任何feature?
     * @param {string} sFeatureID 唯一标识--如:选择的路径id
     * @return {object} 气泡信息--如果有的话，否则null
     */
    selectFeatureByID (sFeatureID) {
      if (this.animSelected && this.animSelected.id === sFeatureID) {
        // return // 当前所选Feature的id与之前选择的id一致；退出不做处理（两次选择相同推出）
        // 改，选择相同信息要返回气泡内容
        const oFeature = this.animSource.getFeatureById(sFeatureID)
        if (oFeature) {
          return oFeature.get('Bubble')
        } else {
          return
        }
      }
      if (this.animSelected && this.animSelected.id !== sFeatureID) { // 如果之前有选择且与当前不同
        // console.log('cleanSelFeatureByID')
        this.cleanSelFeatureByID()
        // this.animSelected = null // 清理方法中释放
      }
      const oFeature = this.animSource.getFeatureById(sFeatureID)
      if (oFeature) { // 找到了所选feature后进行处理;
        const oldStyle = oFeature.getStyle()
        this.animSelected = { id: sFeatureID, style: oldStyle }
        const newStyle = oldStyle.clone()
        const newStroke = newStyle.getStroke()
        newStroke.setColor(this.sMarkColor) // '#F00' 选中色
        newStroke.setLineDash(null)
        newStroke.setWidth(newStroke.getWidth() + 3)
        newStyle.setStroke(newStroke)
        oFeature.setStyle(newStyle)
        // 处理其他关联对象
        const animFeatures = this.animSource.getFeatures()
        // console.log(animFeatures)
        for (let i = 0; i < animFeatures.length; i++) {
          // console.log(animFeatures[i].get('dClass'))
          // console.log(i, animFeatures[i].get('dClass'), animFeatures[i].get('dType'))
          if (animFeatures[i].get('dClass') === sFeatureID) {
            // console.log(animFeatures[i].get('dClass'), animFeatures[i].get('dType'))
            if (animFeatures[i].getId() === sFeatureID) continue // 选择的道路feature上面已经处理了,忽略
            if (animFeatures[i].get('dType') === 'arrow') { // 线段关联的箭头
              const arrowFeatrue = animFeatures[i]
              console.log(arrowFeatrue)
              // const arrowStyle = arrowFeatrue.getStyle().getColor()
              // const arrowImg =  arrowStyle.getImage().getColor()
              const arrowImg = arrowFeatrue.getStyle().getImage().getSrc()
              const rotate = arrowFeatrue.getStyle().getImage().getRotation()
              const newArrowStyle = new Style({
                image: new Icon({
                  color: this.sMarkColor,
                  crossOrigin: 'anonymous',
                  src: arrowImg,
                  anchor: [0.75, 0.5],
                  // rotateWithView: true,
                  rotation: rotate // 从原有样式获取旋转弧度, 不用-rotation
                })
              })
              animFeatures[i].setStyle(newArrowStyle)
            }
            // 处理精灵(如:移动的车辆)
            if (animFeatures[i].get('dType') === 'sprite') { // 线段关联的箭头-待验证
              const spriteFeatrue = animFeatures[i]
              const spriteImgSrc = spriteFeatrue.getStyle().getImage().getSrc()
              const rotate = spriteFeatrue.getStyle().getImage().getRotation()
              // const anchor = spriteFeatrue.getStyle().getImage().getAnchor()
              console.log(spriteImgSrc)
              let spriteImg = null
              if (spriteImgSrc.indexOf('_hl.') !== -1) {
                console.log(spriteImgSrc.indexOf('_hl.'))
                spriteImg = spriteImgSrc
              } else {
                const aTmp = spriteImgSrc.split('.')
                if (aTmp.length !== 2) continue // 返回的图潘地址中不知包含一个. (/)
                spriteImg = aTmp[0] + '_hl.' + aTmp[1] // 将图片设置为高亮(Highlight)图片
              }
              console.log(spriteImg)
              // const aTmp = spriteImgSrc.split('.')
              // if (aTmp.length !== 2) continue // 返回的图潘地址中不知包含一个. (/)
              // const spriteImg = aTmp[0] + '_hl.' + aTmp[1] // 将图片设置为高亮(Highlight)图片
              const newSpriteStyle = new Style({
                image: new Icon({
                  // color: this.sMarkColor, // 设置为标记颜色-修改图标img不改颜色
                  crossOrigin: 'anonymous',
                  src: spriteImg,
                  // anchor: anchor,
                  // rotateWithView: true,
                  rotation: rotate // 从原有样式获取旋转弧度, 不用-rotation
                })
              })
              animFeatures[i].setStyle(newSpriteStyle)
              console.log(animFeatures[i].getGeometry().getCoordinates())
              // console.log(this.oMap.getOverlayById('ovl_spt_' + sFeatureID).getPosition())
            }
          }
        }
        // 信息框处理
        this.addClassStyle(sFeatureID, 'selectedDiv')
        // 返回气泡数据
        return oFeature.get('Bubble')
      }
    },

    /**
     * @description 清除当前所选Feature，还原之前的样式
     * @param {string} sFeatureID 唯一标识--如:选择的路径id
     * @return {object} 气泡信息--如果有的话，否则null
     */
    // cleanSelFeatureByID () {
    //   if (!this.animSelected) return
    //   const sFeatureID = this.animSelected.id
    //   const oFeature = this.animSource.getFeatureById(sFeatureID)
    //   if (oFeature) { // 找到了所选feature后进行处理;
    //     const oldStyle = this.animSelected.style
    //     if (!oldStyle) return
    //     oFeature.setStyle(oldStyle) // 回复Feature原来的样式
    //     // 处理其他关联对象
    //     const animFeatures = this.animSource.getFeatures()
    //     for (let i = 0; i < animFeatures.length; i++) {
    //       // 找到dClass与sFeatureID相同的对象---一个批次的（线 端点 精灵 气泡等）
    //       if (animFeatures[i].get('dClass') === sFeatureID) {
    //         if (animFeatures[i].getId() === sFeatureID) continue // 主feature已经处理完成
    //         // 处理箭头
    //         if (animFeatures[i].get('dType') === 'arrow') { // 线段关联的箭头
    //           const arrowFeatrue = animFeatures[i]
    //           const strokeColor = oldStyle.getStroke().getColor()
    //           const arrowImg = arrowFeatrue.getStyle().getImage().getSrc()
    //           const rotate = arrowFeatrue.getStyle().getImage().getRotation()
    //           const oldArrowStyle = new Style({
    //             image: new Icon({
    //               color: strokeColor,
    //               crossOrigin: 'anonymous',
    //               src: arrowImg,
    //               anchor: [0.75, 0.5],
    //               // rotateWithView: true,
    //               rotation: rotate // 从原有样式获取旋转弧度, 不用-rotation
    //             })
    //           })
    //           animFeatures[i].setStyle(oldArrowStyle)
    //         }
    //         // 处理精灵(如:移动的车辆)
    //         if (animFeatures[i].get('dType') === 'sprite') {
    //           const spriteFeatrue = animFeatures[i]
    //           const spriteImgSrc = spriteFeatrue.getStyle().getImage().getSrc()
    //           const rotate = spriteFeatrue.getStyle().getImage().getRotation()
    //           // const anchor = spriteFeatrue.getStyle().getImage().getAnchor()
    //           const aTmp = spriteImgSrc.split('.')
    //           if (aTmp.length !== 2) continue // 返回的图潘地址中不知包含一个. (/)
    //           const spriteImg = aTmp[0].substr(0, aTmp[0].length - 3) + '.' + aTmp[1] // 去掉串中的‘_hl’(Highlight)
    //           console.log(spriteImg)
    //           const oldSpriteStyle = new Style({
    //             image: new Icon({
    //               // color: '#FFF', // 修改图标img不改颜色
    //               crossOrigin: 'anonymous',
    //               src: spriteImg,
    //               // anchor: anchor,
    //               // rotateWithView: true,
    //               rotation: rotate // 从原有样式获取旋转弧度, 不用-rotation
    //             })
    //           })
    //           animFeatures[i].setStyle(oldSpriteStyle)
    //         }
    //       }
    //     }
    //     this.cleanClassStylr(sFeatureID, 'selectedDiv')
    //     this.animSelected = null
    //   }
    // },
    cleanSelFeatureByID () {
      if (!this.animSelected) return
      const sFeatureID = this.animSelected.id
      const oFeature = this.animSource.getFeatureById(sFeatureID)
      if (oFeature) { // 找到了所选feature后进行处理;
        const oldStyle = this.animSelected.style
        if (!oldStyle) return
        oFeature.setStyle(oldStyle) // 回复Feature原来的样式
        // 处理其他关联对象
        const animFeatures = this.animSource.getFeatures()
        for (let i = 0; i < animFeatures.length; i++) {
          // 找到dClass与sFeatureID相同的对象---一个批次的（线 端点 精灵 气泡等）
          if (animFeatures[i].get('dClass') === sFeatureID) {
            if (animFeatures[i].getId() === sFeatureID) continue // 主feature已经处理完成
            // 处理箭头
            if (animFeatures[i].get('dType') === 'arrow') { // 线段关联的箭头
              const arrowFeatrue = animFeatures[i]
              const strokeColor = oldStyle.getStroke().getColor()
              const arrowImg = arrowFeatrue.getStyle().getImage().getSrc()
              const rotate = arrowFeatrue.getStyle().getImage().getRotation()
              const oldArrowStyle = new Style({
                image: new Icon({
                  color: strokeColor,
                  crossOrigin: 'anonymous',
                  src: arrowImg,
                  anchor: [0.75, 0.5],
                  // rotateWithView: true,
                  rotation: rotate // 从原有样式获取旋转弧度, 不用-rotation
                })
              })
              animFeatures[i].setStyle(oldArrowStyle)
            }
            // 处理精灵(如:移动的车辆)
            if (animFeatures[i].get('dType') === 'sprite') {
              const spriteFeatrue = animFeatures[i]
              const spriteImgSrc = spriteFeatrue.getStyle().getImage().getSrc()
              const rotate = spriteFeatrue.getStyle().getImage().getRotation()
              // const anchor = spriteFeatrue.getStyle().getImage().getAnchor()
              // const aTmp = spriteImgSrc.split('.')
              // if (aTmp.length !== 2) continue // 返回的图潘地址中不知包含一个. (/)
              // const spriteImg = aTmp[0].substr(0, aTmp[0].length - 3) + '.' + aTmp[1] // 去掉串中的‘_hl’(Highlight)
              const spriteImg = spriteImgSrc.replace('_hl', '')
              console.log(spriteImgSrc, spriteImg)
              const oldSpriteStyle = new Style({
                image: new Icon({
                  // color: '#FFF', // 修改图标img不改颜色
                  crossOrigin: 'anonymous',
                  src: spriteImg,
                  // anchor: anchor,
                  // rotateWithView: true,
                  rotation: rotate // 从原有样式获取旋转弧度, 不用-rotation
                })
              })
              animFeatures[i].setStyle(oldSpriteStyle)
            }
          }
        }
        this.cleanClassStylr(sFeatureID, 'selectedDiv')
        this.animSelected = null
      }
    },
    /**
     * @description 清除当前所选Feature样式入口，根据类型清除对应的样式
     * @param {string} sFeatureID 唯一标识--如:选择的路径id
     * @return {object} 气泡信息--如果有的话，否则null
     */
    cleanSelFeature () {
      if (!this.animSelected) return
      const sFeatureID = this.animSelected.id
      if (!sFeatureID) return
      const sType = sFeatureID.substr(0, 3)
      if (sType === 'spt') {
        this.cleanSelSpriteByID(sFeatureID)
      } else {
        this.cleanSelFeatureByID()
      }
    },

    /**
     * @description 为指定气泡添加选中样式边框（通用）
     * @param {String} featureID 选中featrue的id
     * @param {String} cssClassName CSS样式类名
     */
    addClassStyle (featureID, cssClassName) {
      const infoDiv = document.getElementById(featureID)
      if (infoDiv) {
        infoDiv.classList.add(cssClassName)
      }
    },
    // 根据指定的ID删除元素的选中样式（通用）
    cleanClassStylr (featureID, cssClassName) {
      const infoDiv = document.getElementById(featureID)
      if (infoDiv) {
        infoDiv.classList.remove(cssClassName)
      }
    },

    /**
     * @description 更新指定Feature的气泡信息
     * @param {String} sFeatureID 要更新气泡的featrue的id
     * @param {Object} oBubble 要更新的气泡对象 {新气泡中的数据，存在更新，不存在添加}
     */
    updateBubbleByID (sFeatureID, oBubble) {
      if (!oBubble || oBubble === {}) return
      const oFeature = this.animSource.getFeatureById(sFeatureID)
      if (!oFeature) return
      const oldBubble = oFeature.get('Bubble')
      for (const key in oBubble) {
        if (oldBubble[key]) {
          oldBubble[key] = oBubble[key]
        } else {
          // oldBubble.key = oBubble[key]
          oldBubble[key] = oBubble[key]
        }
      }
      // debug
      // console.log(oFeature.get('Bubble'))
    },
    /**
     * @description 清除指定Feature的气泡信息
     * @param {String} sFeatureID 要更新气泡的featrue的id
     * @param {Object} oBubble 要清除的气泡对象 {气泡中存在的key，删除对应的气泡中属性}}
     */
    cleanBubbleByID (sFeatureID, oBubble) {
      if (!oBubble || oBubble === {}) return
      const oFeature = this.animSource.getFeatureById(sFeatureID)
      if (!oFeature) return
      const oldBubble = oFeature.get('Bubble')
      for (const key in oBubble) {
        if (oldBubble[key]) {
          delete oldBubble.key
        }
      }
    },
    /**
     * @description 删除指定的气泡
     * @param {string} sFeatureID 要素ID
     */
    cleanOverlayByID (sFeatureID) {
      const sID = 'ovl_' + sFeatureID // 路径的气泡id是 要素id前加上 'ovl_'
      const oPop = this.oMap.getOverlayById(sID)
      if (oPop) {
        this.oMap.removeOverlay(oPop)
      }
    },
    /**
     * @description 删除指定的气泡
     * @param {string} sFeatureID 要素ID
     */
    createOverlayByID (sFeatureID) {
      const oFeature = this.animSource.getFeatureById(sFeatureID)
      if (!oFeature) return
      const oBubble = oFeature.get('Bubble')
      if (!oBubble || oBubble === {}) return
      const geometry = oFeature.getGeometry()
      const iType = geometry.getType().toLowerCase() // 几何类型
      let aCoord = null
      if (iType === 'linestring') { // 处理线
        aCoord = geometry.getCoordinateAt(0.5)
      }
      if (iType === 'Point') { // 处理点
        aCoord = geometry.getCoordinates()
      }
      if (iType === 'Polygon') { // 处理多边形
        aCoord = geometry.getInteriorPoint()
      }
      // 创建显示气泡
      this.createAnimBubble(sFeatureID, aCoord, oBubble)
    },
    /**
     * @description 删除所有气泡
     */
    cleanAllAnimOverlay () {
      const oCollection = this.oMap.getOverlays()
      // if (!oCollection) return
      const oPop = oCollection.getArray()
      // console.log(oPop)
      const iNum = oPop.length - 1
      for (let i = iNum; i >= 0; i--) {
        const strID = oPop[i].getId()
        // console.log(strID)
        if (strID.substr(0, 3) === 'ovl') {
          this.oMap.removeOverlay(oPop[i])
        }
      }
    },
    /**
     * @description 创建动画层气泡
     * @param {string} sFeatureID 要创建气泡的要素ID
     * @param {Array} aCoord 气泡坐标
     * @param {Object} oBubble 气泡对象
     * @param {boolean} isSimple 是否简单显示
     */
    createAnimBubble (sFeatureID, aCoord, oBubble, isSimple = true) {
      let sInfo = null // 气泡信息
      if (!oBubble || oBubble === {}) return // 如气泡无信息退出创建
      if (isSimple) { // 显示简单数据
        sInfo = oBubble.summary // 获取概览信息
      } else {
        for (const key in oBubble) { // 显示所有气泡信息
          if (key === 'summary') continue
          sInfo = sInfo + key + '：' + oBubble[key] + '<br />'
        }
      }
      // 创建overlay所需HTML元素--DIV
      const roadInfoDIV = document.createElement('div')
      roadInfoDIV.className = 'anim-baseinfo'
      roadInfoDIV.id = sFeatureID
      roadInfoDIV.innerHTML = sInfo
      // 将气泡div添加到HTML--动画层
      const animContainer = document.getElementById('animate-container')
      animContainer.appendChild(roadInfoDIV)
      // 创建overlay层并显示
      const overlay = new Overlay({
        id: 'ovl_' + sFeatureID,
        element: roadInfoDIV,
        positioning: 'center-center',
        stopEvent: false,
        autoPan: true,
        autoPanAnimation: {
          duration: 250
        }
      })
      overlay.setPosition(aCoord)
      this.oMap.addOverlay(overlay)
    },
    /**
     * @description 重新绘制指定元素的气泡-- 可能无法执行
     * @param {string} sFeatureID 要创建气泡的要素ID
     */
    redrawAnimBubbleByID (sFeatureID) {
      this.cleanOverlayByID(sFeatureID)
      this.createOverlayByID(sFeatureID)
    },

    /**
     * @description 获取路径上的点坐标
     * @param {string} sFeatureID 要获取坐标点的
     * @param {float} fraction 获取坐标的位置-线百分比
     * @return {Array} 线上坐标点位置
     */
    getLineCoordinateAt (sFeatureID, fraction) {
      const oFeature = this.animSource.getFeatureById(sFeatureID)
      if (!oFeature) return
      const iType = oFeature.getGeometry().getType().toLowerCase()
      if (iType !== 'linestring') return
      const geometry = oFeature.getGeometry()
      return geometry.getCoordinateAt(fraction)
    }

    // 最后尾
  }
}
